package com.hrpc.discovery.impl;

import com.hrpc.Constant;
import com.hrpc.ServiceConfig;
import com.hrpc.discovery.AbstractRegister;
import com.hrpc.hRpcBootStarp;
import com.hrpc.utils.NetUtils;
import com.hrpc.utils.zookeeper.ZookeeperNode;
import com.hrpc.utils.zookeeper.ZookeeperUtil;
import com.hrpc.watcher.UpAndDownWatcher;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;

import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class ZookeeperRegister extends AbstractRegister {

    //维护一个zookeeper实例
    private ZooKeeper zooKeeper;

    public ZookeeperRegister() {
    }

    public ZookeeperRegister(String connectionString,int timeOut) {
        this.zooKeeper = ZookeeperUtil.createZookeeper(connectionString,timeOut);
    }

    @Override
    public void register(ServiceConfig<?> service) {
        //服务名称的节点
        String parentNode= Constant.BASE_SERVERS+"/"+service.getInterfaceProvider().getName();
        //这个节点应该是个持久节点
        parentNode=parentNode+"/"+service.getGroup();
        if(ZookeeperUtil.exists(zooKeeper,parentNode,null) == false){
            ZookeeperNode zookeeperNode=new ZookeeperNode(parentNode,null);
            ZookeeperUtil.createNode(zooKeeper,zookeeperNode,null, CreateMode.PERSISTENT);
        }
        //创建本机的临时节点，ip:port
        //服务提供方的端口一般自己设定，我们还需要一个获取IP的方法
        //ip我们通过是需要一个局域网IP，不是127.0.0.1，也不是IPV6，应该是192.168.xxx.xxx
        //TODO 端口后续处理端口的问题
        String node=parentNode+"/"+ NetUtils.getIp()+":"+ hRpcBootStarp.getInstance().getConfiguration().getPort();
        if(ZookeeperUtil.exists(zooKeeper,node,null) == false){
            ZookeeperNode zookeeperNode=new ZookeeperNode(node,null);
            //临时节点
            ZookeeperUtil.createNode(zooKeeper,zookeeperNode,null, CreateMode.EPHEMERAL);
        }
    }

    /**
     * 注册中心的核心目的是什么？拉取合适的服务列表
     * @param serverName 服务的名称
     * @return
     */
    @Override
    public List<InetSocketAddress>  lookup(String serverName,String group) {
        //1.找到服务对应的节点，
        String serverNode=Constant.BASE_SERVERS+"/"+serverName + "/" + group;

        //2.从zookeeper中获取他的子节点，192.168.12.123:2151
        List<String> children = ZookeeperUtil.getChildren(zooKeeper, serverNode, new UpAndDownWatcher());
        //获取了所有可用的服务列表
        List<InetSocketAddress> collect = children.stream().map(ipString -> {
            String[] ipAndPort = ipString.split(":");
            String ip = ipAndPort[0];
            int port = Integer.valueOf(ipAndPort[1]);
            return new InetSocketAddress(ip, port);
        }).toList();
        if (collect.size()==0){
            throw new RuntimeException("没有该服务！！！");
        }
        //TODO q1:我们每次调用相关方法的时候都需要去注册中心拉取服务吗？ --本地缓存+watcher
        //     q2:我们如何合理的选择一个可用的服务而不是只获取第一个？--负载均衡
        return collect;
    }
}
